package com.chongdong.service;

import com.alibaba.fastjson.JSON;
import com.chongdong.Constants;
import com.chongdong.dao.nutri.mapper.*;
import com.chongdong.dao.local.mapper.*;
import com.chongdong.entity.imb.ImbPrdBrand;
import com.chongdong.entity.imb.ImbPrdCategory;
import com.chongdong.entity.imb.ImbSysProvider;
import com.chongdong.entity.nutri.*;
import com.chongdong.entity.local.*;
import com.chongdong.entity.saas.PrdImages;
import com.chongdong.entity.saas.SysProvider;
import com.chongdong.util.NameUtils;
import com.github.pagehelper.PageHelper;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class NutriServiceImpl {

    @Autowired
    private NutriSysProviderMapper nutriSysProviderMapper;
    @Autowired
    private NutriPrdBaseMapper nutriPrdBaseMapper;
    @Autowired
    private NutriPrdBrandMapper nutriPrdBrandMapper;
    @Autowired
    private NutriPrdCategoryMapper nutriPrdCategoryMapper;
    @Autowired
    private NutriPrdDetailMapper nutriPrdDetailMapper;
    @Autowired
    private NutriPrdImagesMapper nutriPrdImagesMapper;
    @Autowired
    private NutriPrdBrandProvMapper nutriPrdBrandProvMapper;

    @Autowired
    private LocalPrdBrandMapper localPrdBrandMapper;
    @Autowired
    private LocalSysProviderMapper localSysProviderMapper;
    @Autowired
    private LcoalPrdCategoryMapper lcoalPrdCategoryMapper;
    @Autowired
    private LocalPrdBaseMapper localPrdBaseMapper;
    @Autowired
    private LocalPrdDetailMapper localPrdDetailMapper;
    @Autowired
    private LocalPrdImagesMapper localPrdImagesMapper;
    @Autowired
    private LocalPrdBrandProvMapper localPrdBrandProvMapper;
    private final static Logger logger = LoggerFactory.getLogger(NutriServiceImpl.class);


    /**
     * 更新商品图片信息，
     */
    public void trnsferPrdImageNutriData2SaaSPlatform(Integer pageNum, Integer pageSize) {
        pageNum = (pageNum == null ? 1 : pageNum);
        pageSize = (pageSize == null ? 5000 : pageSize);
        while (pageSize > 0) {
            PageHelper.startPage(1, pageSize);
            List<NutriPrdImages> nutriPrdImages = nutriPrdImagesMapper.selectAllWithSaasIdIsNull();
            LocalPrdImages prdImages = new LocalPrdImages();
            nutriPrdImages.forEach(img -> {
                //替换为saasprdId的图片信息
                NutriPrdImages images = nutriPrdImagesMapper.getSaasInfoByImgId(img.getId());
                List<LocalPrdImages> select = localPrdImagesMapper.select(new LocalPrdImages(images.getPrdId()));
                if (select.size() < 1) {//saas上不存在
                    try {
                        BeanUtils.copyProperties(prdImages, images);
                    } catch (Exception e) {
                        logger.error("当前执行的模块为营养所更新商品图片信息，错误信息为" + JSON.toJSONString(img));
                        e.printStackTrace();
                    }
                    prdImages.setId(null);
                    localPrdImagesMapper.insertSelective(prdImages);
                    if (Constants.ISUPDATE) {
                        img.setSaasPrdId(prdImages.getId());
                        nutriPrdImagesMapper.updateByPrimaryKeySelective(img);
                    }
                } else {
                    if (Constants.ISUPDATE) {
                        img.setSaasPrdId(select.get(0).getId());
                        nutriPrdImagesMapper.updateByPrimaryKeySelective(img);
                    }
                }

                logger.info("当前执行的模块为更新营养所商品信息");
            });
            pageNum++;
            pageSize = nutriPrdImages.size() == pageSize ? nutriPrdImages.size() : -1;
        }

    }

    /**
     * 更新商品详情信息，判断标准是PRD_ID，PRV_ID，CODE，DETAIL_INFO
     */
    public void trnsferPrdDetailNutriData2SaaSPlatform(Integer pageNum, Integer pageSize) throws Exception {
        pageNum = (pageNum == null ? 1 : pageNum);
        pageSize = (pageSize == null ? 5000 : pageSize);
        while (pageSize > 0) {
            PageHelper.startPage(1, pageSize);
            List<NutriPrdDetail> nutriPrdDetails = nutriPrdDetailMapper.selectAllWithSaasIdIsNull();
            LocalPrdDetail prdDetail = new LocalPrdDetail();
            nutriPrdDetails.forEach(detail -> {
                NutriPrdDetail d = nutriPrdDetailMapper.getSaasInfoByImgId(detail.getId());
                List<LocalPrdDetail> select = localPrdDetailMapper.select(new LocalPrdDetail(d.getPrdId(), d.getPrvId(), d.getCode()));
                if (select.size() < 1) {//未找到
                    try {
                        BeanUtils.copyProperties(prdDetail, d);
                    } catch (Exception e) {
                        logger.error("当前执行的模块为营养所更新商品详情，错误数据为" + JSON.toJSONString(detail));
                        e.printStackTrace();
                    }
                    prdDetail.setId(null);
                    localPrdDetailMapper.insertSelective(prdDetail);
                    if (Constants.ISUPDATE) {
                        detail.setSaasPrdId(prdDetail.getId());
                        nutriPrdDetailMapper.updateByPrimaryKeySelective(detail);
                    }
                } else {
                    if (Constants.ISUPDATE) {
                        detail.setSaasPrdId(select.get(0).getId());
                        nutriPrdDetailMapper.updateByPrimaryKeySelective(detail);
                    }
                }
            });
            logger.info("当前执行的模块为营养所商品详情，已结束页码为" + pageNum);
            pageNum++;
            pageSize = nutriPrdDetails.size() == pageSize ? nutriPrdDetails.size() : -1;
        }

    }

    /**
     * 将商家数据合并到saas平台,总体合并逻辑为saas上存在则更新本地系统saas_id,不存在则保存至saas平台，同时更新本地系统saas_id,
     * 供应商去重以name为基准
     */
    public void transferProviderNutriData2SaaSPlatform() throws Exception {
        Map<String, Long> providerMap = localSysProviderMapper.selectAll().stream().collect(Collectors.toMap(LocalSysProvider::getName, LocalSysProvider::getId));

        //1.查询所有数据
        List<NutriSysProvider> sysProviders = nutriSysProviderMapper.selectAllwithSaasIdIsNull();
        Date createTime = new Date();
        Date updateTime = new Date();
        //2.将所有数据导入数据库
        sysProviders.forEach(p -> {
            if (providerMap.get(NameUtils.getFinalSysProviderName(p.getName(), NameUtils.NUTRI)) != null) {
                p.setSaasPrvId(providerMap.get(NameUtils.getFinalSysProviderName(p.getName(), NameUtils.NUTRI)));
                nutriSysProviderMapper.updateByPrimaryKeySelective(p);
            } else {
                LocalSysProvider sysProvider = copyNutriProviderValue(p, createTime, updateTime);
                //设置最终显示名称
                sysProvider.setName(NameUtils.getFinalSysProviderName(p.getName(), NameUtils.NUTRI));
                localSysProviderMapper.insertSelective(sysProvider);
                providerMap.put(p.getName(), p.getSaasPrvId());
                if (Constants.ISUPDATE) {
                    p.setSaasPrvId(sysProvider.getId());
                    nutriSysProviderMapper.updateByPrimaryKeySelective(p);
                }
            }
            try {
                saveByrProtocolInfo(providerMap.get(p.getName()));
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("运行出错，请查看日志,执行业务模块为合并营养所商家");
            }

        });
    }

    @Transactional(value = "localTransactionManager")
    public void saveByrProtocolInfo(Long prvId) throws Exception {
        //同步协议供应商信息，对应byr_protocol_provider表
        localSysProviderMapper.insertByrProtocalProvider(Constants.NUTRIORGID, prvId,
                Constants.prvType, Constants.providerStatus, new Date(), new Date());

        //同步买家(企业)协议供货商表byr_protocol
        localSysProviderMapper.insertbyrProtocol(Constants.NUTRIORGID, prvId,
                "nutriLine" + prvId, Constants.protocolStatus, Constants.protocalType, Constants.protocolRate);
    }

    /**
     * 将品牌数据合并到saas平台,总体合并逻辑为saas上存在则更新本地系统saas_id,不存在则保存至saas平台，同时更新本地系统saas_id,
     * 品牌去重以品牌name为基准
     */
    public void trnansferBrandData2SaasPlatform() throws Exception {

        Map<String, Long> brandMap = localPrdBrandMapper.selectAll().stream().collect(Collectors.toMap(LocalPrdBrand::getName, LocalPrdBrand::getId));
        //查询所有数据
        List<NutriPrdBrand> prdBrands = nutriPrdBrandMapper.selectAllWithSaasIdIsNull();
        //2.将数据导入数据库
        LocalPrdBrand prdBrand = new LocalPrdBrand();
        prdBrands.forEach(p -> {
            //查询saas是否存在该品牌，如果存在则更新本地系统中的Saaasid
            //在查询前获取saas上对应名称
            p.setName(NameUtils.getFinalPrdBrandName(p.getName(), NameUtils.NUTRI));
            if (brandMap.get(p.getName()) != null) {
                p.setSaasBrandId(brandMap.get(p.getName()));
                p.setNameEn(NameUtils.getFinalPrdBrandNameEn(p.getNameEn(), NameUtils.NUTRI));
                nutriPrdBrandMapper.updateByPrimaryKeySelective(p);
            } else {
                try {
                    BeanUtils.copyProperties(prdBrand, p);
                } catch (Exception e) {
                    logger.error("当前执行到的模块为营养所合并品牌，错误数据是" + JSON.toJSONString(p));
                    logger.error(e.toString());
                    throw new RuntimeException("转换失败");
                }
                prdBrand.setNameEn(NameUtils.getFinalPrdBrandNameEn(p.getNameEn(), NameUtils.NUTRI));
                prdBrand.setId(null);
                localPrdBrandMapper.insertSelective(prdBrand);
                brandMap.put(p.getName(), prdBrand.getId());
                p.setSaasBrandId(prdBrand.getId());
                p.setNameEn(NameUtils.getFinalPrdBrandNameEn(p.getNameEn(), NameUtils.NUTRI));
                nutriPrdBrandMapper.updateByPrimaryKeySelective(p);
            }
        });
    }

    /**
     * 将类目信息合并到saas平台，根据运营人员给出的类目映射关系可知，药生所的类目集合是华理类目集合的真子集，且对应关系完好，所以药生所类目只需要根据
     * 本地系统类目名称在saas找到对应的id即可
     */
    public void transferCategoryData2Platform() throws Exception {
        Map<String, Long> categoryMap = lcoalPrdCategoryMapper.selectAll().stream().collect(Collectors.toMap(LocalPrdCategory::getName, LocalPrdCategory::getId));

        nutriPrdCategoryMapper.selectAllWithSaasIdIsNull().forEach(p -> {
            p.setSaasCategoryId(categoryMap.get(p.getName()));
            nutriPrdCategoryMapper.updateByPrimaryKeySelective(p);
        });
    }

    /**
     * 将商品数据合并到saas平台
     */
    public void trnsferProductNutriData2SaaSPlatform(Integer pageNum, Integer pageSize) throws Exception {

        Map<Long, Long> providerMap = nutriSysProviderMapper.selectAll().stream().collect(Collectors.toMap(NutriSysProvider::getId, NutriSysProvider::getSaasPrvId));
        Map<Long, Long> brandMap = nutriPrdBrandMapper.selectAll().stream().collect(Collectors.toMap(NutriPrdBrand::getId, NutriPrdBrand::getSaasBrandId));

        Map<Long, Long> categoryMap = nutriPrdCategoryMapper.selectAll().stream().collect(Collectors.toMap(NutriPrdCategory::getId, NutriPrdCategory::getSaasCategoryId));

        pageNum = (pageNum == null ? 1 : pageNum);
        pageSize = (pageSize == null ? 5000 : pageSize);
        while (pageSize > 0) {
            PageHelper.startPage(1, pageSize);
            //1.查询所有数据
            List<NutriPrdBase> nutriPrdBases = nutriPrdBaseMapper.selectAll();
            //2.将数据导入数据库
            Date createTime = new Date();
            Date updateTime = new Date();
            nutriPrdBases.forEach(p -> {
                Long pid = p.getId();
                Long prvId = providerMap.get(p.getPrvId());
                Long brandId = brandMap.get(p.getBrandId());
                List<LocalPrdBase> select = localPrdBaseMapper.select(new LocalPrdBase(p.getName(), prvId, brandId, p.getCode()));
                LocalPrdBase prdBase = null;
                try {
                    prdBase = copyNutriPrdBaseValue(p, createTime, updateTime);
                } catch (InvocationTargetException e) {
                    logger.info("当前执行的模块为营养所<<合并商品>>错误数据为" + JSON.toJSONString(p));
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    logger.info("当前执行的模块为营养所<<合并商品>>错误数据为" + JSON.toJSONString(p));
                    e.printStackTrace();
                }
                if (select.size() < 1) {
                    prdBase.setBrandId(brandId);
                    prdBase.setPrvId(prvId);
                    prdBase.setCategoryId(categoryMap.get(p.getCategoryId()));
                    prdBase.setId(null);
                    localPrdBaseMapper.insertSelective(prdBase);
                    if (Constants.ISUPDATE) {
                        p.setSaaSPrdId(prdBase.getId());
                        nutriPrdBaseMapper.updateByPrimaryKeySelective(p);
                    }
                } else {
                    if (Constants.ISUPDATE) {
                        p.setSaaSPrdId(select.get(0).getId());
                        nutriPrdBaseMapper.updateByPrimaryKeySelective(p);
                    }
                }
            });
            logger.info("当前执行的模块为营养所商品数据，已结束页码为" + pageNum);
            pageNum++;
            pageSize = nutriPrdBases.size() == pageSize ? nutriPrdBases.size() : -1;
        }

    }

    /**
     * 更新商家资质信息prd_brand_prov
     */

    public void transferSysProviderAndBrandRelation() {
        Map<Long, Long> providerMap = nutriSysProviderMapper.selectAll().stream().collect(Collectors.toMap(NutriSysProvider::getId, NutriSysProvider::getSaasPrvId));
        Map<Long, Long> brandMap = nutriPrdBrandMapper.selectAll().stream().collect(Collectors.toMap(NutriPrdBrand::getId, NutriPrdBrand::getSaasBrandId));
        List<NutriPrdBrandProv> huaLiPrdBrandProvs = nutriPrdBrandProvMapper.selectAll();
        LocalPrdBrandProv prdBrandProv = new LocalPrdBrandProv();
        huaLiPrdBrandProvs.forEach(p -> {
            try {
                BeanUtils.copyProperties(prdBrandProv, p);
            } catch (IllegalAccessException e) {
                logger.error("当前执行的业务模块为营养所更新商家资质信息，错误数据为" + JSON.toJSONString(p));
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                logger.error("当前执行的业务模块为营养所更新商家资质信息，错误数据为" + JSON.toJSONString(p));
                e.printStackTrace();
            }
            p.setPrvId(providerMap.get(p.getPrvId()));
            p.setBrandId(brandMap.get(p.getBrandId()));
            List<LocalPrdBrandProv> select = localPrdBrandProvMapper.select(new LocalPrdBrandProv(p.getBrandId(), p.getPrvId()));
            if (select.size() < 1) {
                prdBrandProv.setId(null);
                localPrdBrandProvMapper.insertSelective(prdBrandProv);
            }
        });
    }

    /**
     * 对象
     *
     * @param source
     * @param createTime
     * @param updateTime
     * @return
     */
    public LocalSysProvider copyNutriProviderValue(NutriSysProvider source, Date createTime, Date updateTime) {
        LocalSysProvider dest = new LocalSysProvider();
        dest.setName(source.getName());
        dest.setAddress(source.getAddress());
        dest.setApproveStatus(source.getStatus());
        dest.setType(source.getType());
        dest.setLogo(source.getLogo());
        dest.setCreateTime(createTime);
        dest.setContact(source.getContact());
        dest.setTelephone(source.getTelephone());
        dest.setEmail(source.getEmail());
        dest.setSysNum(source.getSysNum());
        dest.setStatus(source.getStatus());
        dest.setAreaId(source.getAreaId());
        dest.setShortName(StringUtils.isBlank(source.getShortName()) ? "" : source.getShortName());
        dest.setTaxNo(source.getTaxNo());
        dest.setBank(source.getAcctBank());
        dest.setBankAccount(source.getAccount());
        dest.setLicenseUrl(source.getLicenseUrl());
        dest.setUpdateTime(updateTime);
        return dest;
    }

    public LocalPrdBase copyNutriPrdBaseValue(NutriPrdBase source, Date createTime, Date updateTime) throws InvocationTargetException, IllegalAccessException {
        LocalPrdBase prdBase = new LocalPrdBase();
        BeanUtils.copyProperties(prdBase, source);
        prdBase.setCreateTime(createTime);
        prdBase.setUpdateTime(updateTime);
        return prdBase;
    }


}
